#include <iostream>
#include <memory>
#include "Tcp_Server.hpp"
#include "Protocol.hpp"
#include "Log.hpp"
#include "Daemon.hpp"

using namespace ns_tcp_server;
using namespace ns_protocol;

static void Usage(const char *str)
{
    std::cout << "\n Usage:" << str << " port\n"
              << std::endl;
}

Response calculatorhelp(const Request &req)
{
    Response res(0, 0, req._x, req._y, req._op);
    switch (req._op)
    {
    case '+':
        res._result = req._x + req._y;
        break;
    case '-':
        res._result = req._x - req._y;
        break;
    case '*':
        res._result = req._x * req._y;
        break;
    case '/':
        if(req._y == 0) res._status = 2; // 除0错误
        else res._result = req._x / req._y;
        break;
    case '%':
        if(req._y == 0) res._status = 3; // 求余0错误
        else res._result = req._x % req._y;
        break;
    default:
        res._status = 4; // 未定义符号
        break;
    }
    return res;
}

// 服务器需要执行的函数
void calculator(int sock)
{
    char buffer[1024];
    // 计算任务(序列化，反序列化)
    while (true)
    {
        // 接收
        ssize_t sz = recv(sock, buffer, sizeof(buffer) - 1, 0);
        if (sz > 0)
        {
            buffer[sz] = 0;
        }
        else if (sz == 0)
        {
            Messagelog(NORMAL, "客户端已经关闭,服务结束");
            break;
        }
        else if (sz < 0)
        {
            Messagelog(ERROR, "recv sock[%d] error: %d-%s", sock, errno, strerror(errno));
            break;
        }
        // 剪去报头
        std::string recv_str = buffer;
        std::string message = Decode(recv_str);
        if(message.empty()) continue;
        // 反序列化
        Request req;
        Response res;
        if (req.Deserialize(message) == false)
        {
            std::cout << "反序列化错误" << std::endl;
            res._status = 1; // 反序列化错误
        }
        // 处理数据，进行计算
        else
        {
            res = calculatorhelp(req);
        }
        // 序列化
        std::string str = res.Serialize();
        // 添加报头
        std::string send_message = Encode(str);

        // 发送
        sz = send(sock, send_message.c_str(), send_message.size(), 0);
        if (sz <= 0)
        {
            Messagelog(ERROR, "send sock[%d] error: %d-%s", sock, errno, strerror(errno));
            break;
        }
    }
}

// ./ CalServer port
int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        Usage(argv[0]);
        exit(1);
    }
    Daemon();

    std::unique_ptr<TcpServer> server(new TcpServer(atoi(argv[1])));
    server->BindServer(calculator);
    server->start();

    return 0;
}